This section provides sample code shown in Listing 16-1 for a Macintosh data handler component.
While data handler components to be used with QuickTime for Windows are functionally quite similar to Macintosh data handlers, there are some differences. QuickTime for Windows does not support a write data path. Therefore, your data handler needs to support only those functions that allow QuickTime to read movie data. In addition, Windows components are built as special dynamic link libraries (DLLs). You need to structure your code appropriately. For more information and a sample Windows data handler, see Creating Custom Components: QuickTime for Windows.
Listing 1 Sample Macintosh Data Handler
#include <Aliases.h>
#include <Files.h>
#include <OSUtils.h>
#include "DataHandlerPrototypes.h"
// these selectors belong in the header file
enum {DataGetDataSelector = 2 };
enum {DataPutDataSelector = 3 };
enum {DataOpenForWriteSelector = 5 };
enum {DataCloseForWriteSelector = 6 };
enum {DataOpenForReadSelector = 8 };
enum {DataCloseForReadSelector = 9 };
enum {DataSetAliasSelector = 10 };
enum {DataGetAliasSelector = 11 };
enum {DataCompareAliasSelector = 12 };
enum {DataTaskSelector = 13 };
enum {DataScheduleDataSelector = 14 };
enum {DataCanUseDataRef = 19 };
enum {DataGetVolumeListSelector = 20 };
// data structures
typedef struct {
ComponentInstance self;
AliasHandle alias;
short readFref;
short writeFref;
} DataHandlerGlobalsRecord, *DataHandlerGlobals;
// function declarations
pascal ComponentResult main(ComponentParameters *params,
Handle storage);
ComponentFunctionUPP DHSelectorLookup(short selector);
pascal ComponentResult DHOpen(DataHandlerGlobals storage,
ComponentInstance self);
pascal ComponentResult DHClose(DataHandlerGlobals storage,
ComponentInstance self);
pascal ComponentResult DHCanDo(DataHandlerGlobals storage,
short functionSelector);
pascal ComponentResult DHVersion( DataHandlerGlobals storage);
pascal ComponentResult DHGetData(DataHandlerGlobals storage, Handle h,
long offsetIntoHandle, long offset,
long size);
pascal ComponentResult DHPutData(DataHandlerGlobals storage, Handle h,
long hOffset, long *offset, long size);
pascal ComponentResult DHSetAlias(DataHandlerGlobals storage,
AliasHandle alias);
pascal ComponentResult DHGetAlias(DataHandlerGlobals storage,
AliasHandle *alias);
pascal ComponentResult DHCompareAlias(DataHandlerGlobals storage,
AliasHandle alias, Boolean *equal);
pascal ComponentResult DHScheduleData (DataHandlerGlobals storage,
Ptr dataPtr,long fileOffset,
long dataSize, long refCon,
TimeRecord *timeNeededBy,
DataHCompletionUPP completionRoutine);
pascal ComponentResult DHOpenForRead(DataHandlerGlobals storage);
pascal ComponentResult DHCloseForRead(DataHandlerGlobals storage);
pascal ComponentResult DHOpenForWrite(DataHandlerGlobals storage);
pascal ComponentResult DHCloseForWrite(DataHandlerGlobals storage);
pascal ComponentResult DHGetVolumeList(DataHandlerGlobals storage,
DataHVolumeList *volumeList);
pascal ComponentResult DHCanUseDataRef(DataHandlerGlobals storage,
Handle dataRef, long *useFlags);
// main function
pascal ComponentResult main(ComponentParameters *params, Handle storage)
{
ComponentResult err;
ComponentFunctionUPP componentProc;
componentProc = DHSelectorLookup(params->what);
if (componentProc)
err = CallComponentFunctionWithStorage(storage, params,
componentProc);
else
err = badComponentSelector;
return err;
}
// determine function based on selected request
ComponentFunctionUPP DHSelectorLookup(short selector)
{
ComponentFunctionUPPcomponentProc = 0;
switch (selector) {
case kComponentVersionSelect:
componentProc = (ComponentFunctionUPP)DHVersion;
break;
case kComponentCanDoSelect:
componentProc = (ComponentFunctionUPP)DHCanDo;
break;
case kComponentCloseSelect:
componentProc = (ComponentFunctionUPP)DHClose;
break;
case kComponentOpenSelect:
componentProc = (ComponentFunctionUPP)DHOpen;
break;
case DataGetDataSelector:
componentProc = (ComponentFunctionUPP)DHGetData;
break;
case DataPutDataSelector:
componentProc = (ComponentFunctionUPP)DHPutData;
break;
case DataOpenForReadSelector:
componentProc = (ComponentFunctionUPP)DHOpenForRead;
break;
case DataCloseForReadSelector:
componentProc = (ComponentFunctionUPP)DHCloseForRead;
break;
case DataOpenForWriteSelector:
componentProc = (ComponentFunctionUPP)DHOpenForWrite;
break;
case DataCloseForWriteSelector:
componentProc = (ComponentFunctionUPP)DHCloseForWrite;
break;
case DataSetAliasSelector:
componentProc = (ComponentFunctionUPP)DHSetAlias;
break;
case DataGetAliasSelector:
componentProc = (ComponentFunctionUPP)DHGetAlias;
break;
case DataCompareAliasSelector:
componentProc = (ComponentFunctionUPP)DHCompareAlias;
break;
case DataScheduleDataSelector:
componentProc = (ComponentFunctionUPP)DHScheduleData;
break;
case DataCanUseDataRef:
componentProc = (ComponentFunctionUPP)DHCanUseDataRef;
break;
case DataGetVolumeListSelector:
componentProc = (ComponentFunctionUPP)DHGetVolumeList;
break;
}
return componentProc;
}
// open data handler connection
pascal ComponentResult DHOpen(DataHandlerGlobals storage,
ComponentInstance self)
{
ComponentResult err;
storage = (DataHandlerGlobals)NewPtrClear(sizeof(DataHandlerGlobalsRecord));
if (err = MemError())
return err;
storage->self = (ComponentInstance)self;
SetComponentInstanceStorage(storage->self,(Handle)storage);
return noErr;
}
// close component connection
pascal ComponentResult DHClose(DataHandlerGlobals storage,
ComponentInstance self)
{
if (storage != nil) {
DHCloseForRead(storage);
DHCloseForWrite(storage);
if (storage->alias != nil)
DisposeHandle((Handle)storage->alias);
DisposePtr((Ptr)storage);
}
return noErr;
}
// determine whether data handler supports request
pascal ComponentResult DHCanDo(DataHandlerGlobals storage,
short functionSelector)
{
return DHSelectorLookup(functionSelector) != 0;
}
// return component's version
pascal ComponentResult DHVersion(DataHandlerGlobals storage)
{
return 0x00020001;
}
// read data
pascal ComponentResult DHGetData(DataHandlerGlobals storage, Handle h,
long offsetIntoHandle, long offset, long
size)
{
OSErr err;
SignedBytesaveState;
if (!storage->readFref) {
err = DHOpenForRead(storage);
if (err != noErr)
return err;
}
saveState = HGetState(h);
HLock(h);
err = DHScheduleData(storage, *h + offsetIntoHandle,
offset, size, 0, nil, nil);
HSetState(h, saveState);
return err;
}
// write data
pascal ComponentResult DHPutData(DataHandlerGlobals storage, Handle h,
long hOffset, long *offset, long size)
{
OSErr err;
if (!storage->writeFref) {
err = DHOpenForWrite(storage);
if (err != noErr)
return err;
}
err = SetFPos(storage->writeFref, fsFromLEOF, 0);
if (err == noErr) {
if (offset)
err = GetFPos(storage->writeFref, offset);
if (err == noErr)
err = FSWrite(storage->writeFref, &size